3D Graphics Programming with QuickDraw 3D 1.5.4
Previous | QD3D Book | Overview | Chapter Contents | Next |
As explained in "Modeling and Rendering" , creating an image of a three-dimensional model involves several steps. You must first create a model and then specify key information about the scene (such as the lighting and camera angle). This section shows how to create a simple model containing three-dimensional objects.
Objects in QuickDraw 3D are defined using a Cartesian coordinate system that is right-handed (that is, if the thumb of the right hand points in the direction of the positive x axis and the index finger points in the direction of the positive y axis, then the middle finger, when made perpendicular to the other two fingers, points in the direction of the positive z axis). Figure 5 shows a right-handed coordinate system.
For a more complete description of the coordinate spaces used by QuickDraw 3D, see the chapter "Transform Objects" later in this book.
Figure 5 A right-handed Cartesian coordinate system
The model created by the MyNewModel function defined in Listing 4 consists of a number of boxes that spell out the words "Hello World." The words are written in block letters, with each letter composed of a number of individual boxes. MyNewModel uses the inelegant but straightforward method of defining the 34 boxes by creating four arrays of 34 elements each. As described in the chapter "Geometric Objects" , a box is defined by four pieces of information, an origin and three vectors that specify its sides:
typedef struct TQ3BoxData {
TQ3Point3D origin;
TQ3Vector3D orientation;
TQ3Vector3D majorAxis;
TQ3Vector3D minorAxis;
TQ3AttributeSet *faceAttributeSet;
TQ3AttributeSet boxAttributeSet;
} TQ3BoxData;
First, MyNewModel creates a new and empty ordered display group to contain all the boxes. Then the function loops through the data arrays, creating boxes and adding them to the group.
TQ3GroupObject MyNewModel (void)
{
TQ3GroupObject myModel;
TQ3GeometryObject myBox;
TQ3BoxData myBoxData;
TQ3GroupPosition myGroupPosition;
/*Data for boxes comprising Hello and World block letters.*/
long i;
float xorigin[34] = {
-12.0, -9.0, -11.0, -7.0, -6.0, -6.0, -6.0, -2.0, -1.0,
3.0, 4.0, 8.0, 9.0, 9.0, 11.0, -13.0, -12.0, -11.0, -9.0,
-7.0, -6.0, -6.0, -4.0, -2.0, -1.0, -1.0, 1.0, 1.0, 3.0,
4.0, 8.0, 9.0, 9.0, 11.0};
float yorigin[34] = {
0.0, 0.0, 3.0, 0.0, 6.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
6.0, 0.0, 0.0, -8.0, -8.0, -7.0, -8.0, -8.0, -8.0, -2.0,
-8.0, -8.0, -2.0, -5.0, -4.0, -8.0, -8.0, -8.0, -8.0, -8.0,
-2.0, -7.0};
float height[34] = {
7.0, 7.0, 1.0, 7.0, 1.0, 1.0, 1.0, 7.0, 1.0, 7.0, 1.0, 7.0,
1.0, 1.0, 7.0, 7.0, 1.0, 3.0, 7.0, 7.0, 1.0, 1.0, 7.0, 7.0,
1.0, 1.0, 2.0, 3.0, 7.0, 1.0, 7.0, 1.0, 1.0, 5.0};
float width[34] = {
1.0, 1.0, 2.0, 1.0, 3.0, 2.0, 3.0, 1.0, 3.0, 1.0, 3.0, 1.0,
2.0, 2.0, 1.0, 1.0, 3.0, 1.0, 1.0, 1.0, 2.0, 2.0, 1.0, 1.0,
2.0, 2.0, 1.0, 1.0, 1.0, 3.0, 1.0, 2.0, 2.0, 1.0};
/*Create an ordered display group for the complete model.*/
myModel = Q3OrderedDisplayGroup_New();
if (myModel == NULL)
goto bail;
/*Add all the boxes to the model.*/
myBoxData.faceAttributeSet = NULL;
myBoxData.boxAttributeSet = NULL;
for (i=0; i<34; i++) {
Q3Point3D_Set(&myBoxData.origin, xorigin[i], yorigin[i], 1.0);
Q3Vector3D_Set(&myBoxData.orientation, 0, height[i], 0);
Q3Vector3D_Set(&myBoxData.minorAxis, width[i], 0, 0);
Q3Vector3D_Set(&myBoxData.majorAxis, 0, 0, 2);
myBox = Q3Box_New(&myBoxData);
myGroupPosition = Q3Group_AddObject(myModel, myBox);
/*now that myBox has been added to group, dispose of our reference*/
Q3Object_Dispose(myBox);
if (myGroupPosition == NULL)
goto bail;
}
return (myModel); /*return the completed model*/
bail:
/*If any of the above failed, then return an empty model.*/
return (NULL);
}
The MyNewModel function can leak memory. Your application should use a different error-recovery strategy than is used in Listing 4 .
If successful, MyNewModel returns the group object containing the 34 boxes to its caller.
Previous | QD3D Book | Overview | Chapter Contents | Next |